#pragma once

#include <iostream>
#include <string>
#include <json/json.h>

// #define MySelf 1

const std::string blank_space_sep=" "; // 默认内容分隔符
const std::string protocol_sep="\n"; //默认协议分隔符

std::string Encode(const std::string& content) // 封装报头
{
    std::string package = std::to_string(content.size());
    package += protocol_sep;
    package += content;
    package += protocol_sep;

    return package;
}

//"len"\n"x op y"\n 
bool Decode(std::string &package, std::string *content) // 解码
{
    std::size_t pos = package.find(protocol_sep);
    if(pos == std::string::npos) 
        return false;

    std::string len_str = package.substr(0, pos);
    std::size_t len = std::stoi(len_str);
    
    // package = len_str + content_str + 2
    std::size_t total_len = len_str.size() + len + 2;
    
    if(package.size() < total_len) 
        return false;

    *content = package.substr(pos+1, len);
    
    // earse 移除报文 package.erase(0, total_len);
    package.erase(0, total_len);

    return true;    
}

//json protobuf
//json用来序列化和反序列化
class Request
{
public:
    Request(int data1,int data2,char oper)
        :x(data1),y(data2),op(oper)
    {}

    Request()
    {}

public:
    bool Serialize(std::string *out) //序列化
    {
#ifdef MySelf        
        //构建报文的有效载荷
        //struct => string, "x op y" => "len"\n"x op y"
        std::string s=std::to_string(x);
        s+=blank_space_sep;
        s+=op;
        s+=blank_space_sep;
        s+=std::to_string(y);

        //封装报头
        //*out=std::to_string(s.size());
        //*out+=protocol_sep;
        *out+=s;
        return true;
#else 
        Json::Value root;
        root["x"] = x;
        root["y"] = y;
        root["op"] = op;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif
    }

    bool Deserialize(const std::string &in) //反序列化
    {
#ifdef MySelf        
        //"len"\n"x op y"
        std::size_t left = in.find(blank_space_sep);
        if (left == std::string::npos)
            return false;
            
        std::string part_x = in.substr(0, left);

        std::size_t right = in.rfind(blank_space_sep);
        if (right == std::string::npos)
            return false;

        std::string part_y = in.substr(right + 1);

        if (left + 2 != right)
            return false;
        
        op = in[left + 1];
        x = std::stoi(part_x);
        y = std::stoi(part_y);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        x = root["x"].asInt();
        y = root["y"].asInt();
        op = root["op"].asInt();
        return true;
#endif        
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x << op << y << "=?" << std::endl;
    }

public:
    int x;
    int y;
    char op; // + - * / %
};

class Response
{
public:
    Response(int res,int c)
        :result(res),code(c)
    {}

    Response()
    {}

public:
    bool Serialize(std::string *out) //序列化
    {
#ifdef MySelf        
        //构建报文的有效载荷
        //"len"\n"result code"
        std::string s=std::to_string(result);
        s+=blank_space_sep;
        s+=std::to_string(code);

        //封装报头
        //*out=std::to_string(s.size());
        //*out+=protocol_sep;
        *out+=s;
        return true;
#else
        Json::Value root;
        root["result"] = result;
        root["code"] = code;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif        
    }

    bool Deserialize(const std::string &in) //反序列化
    {
#ifdef MySelf        
        //"result code"
        std::size_t pos = in.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;

        std::string part_left = in.substr(0, pos);
        std::string part_right = in.substr(pos+1);

        result = std::stoi(part_left);
        code = std::stoi(part_right);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        result = root["result"].asInt();
        code = root["code"].asInt();
        return true;
#endif        
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << result << ", code: "<< code << std::endl;
    }

public:
    int result;
    int code; // 0 可信 否则是不同的错误码
};